package board;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.awt.Point;
import  ball.*;
public class Board {
	private Map<Point,Ball> ballArray=new HashMap<Point, Ball>();
	private Ball[] balls={new Ball(0,0,'3'),new Ball(1,0,'4'),new Ball(0,5,'0')};
	private Ball ball;
	private int score; 
	public Board(){
		for(int i=0;i<6;i++){
			for(int j=0;j<6;j++){
				this.ballArray.put(new Point(i,j), null);
			}
		}
		this.setUp();
		this.ball = this.getNextRandomBall();
	/*	Ball ball = new Ball(0,0,'5');
		this.setBall(ball);
		*/
	}
	private void setUp(){
		for(int i=0;i<this.balls.length;i++){
			this.ballArray.put(new Point(balls[i].getRow(),this.balls[i].getCol()),this.balls[i]);
		}
	}
	
	public void setBall (Ball ball){
		this.ball = ball;
	}
	
	public Ball getBall (){
		return this.ball;
	}
	
	public void setBallArray (Map<Point,Ball> testBallArray){
		this.ballArray = testBallArray;
	}
	
	

	public Map<Point,Ball> getBallArray(){
		return this.ballArray;
	}
	public void print(){
		for(int i = 0 ; i<8;i++){
			System.out.print("*");
		}
		System.out.println("");
		for(int i = 0; i<6 ;i++){
			System.out.print("*");
			for(int j = 0; j<6;j++){
				Ball temp = this.ballArray.get(new Point(i,j));
				if(temp!=null)
					System.out.print(temp.getType());	
				else
					System.out.print(" ");
			}
			System.out.print("*");
			System.out.println("");
		}
		for(int i = 0 ; i<8;i++){
			System.out.print("*");
		}
		System.out.print(" "+"Score"+" : "+ this.score);
		System.out.println("");
		System.out.println("   "+this.ball.getType());
	}
	private Ball getNextRandomBall(){
		Random random = new Random();
		int randomNumber = random.nextInt(5) + 1;
		char type = (char) (randomNumber+'0');
		Ball next = this.getNextBall(type);
		return next;
	}
	
	//get next ball
	public Ball getNextBall(char c){
		Ball next = new Ball(0,0,c);
		return next;
	}
	
	//Find the row which is the lowest for a particular column
	
	public int getLowestRow(int col){
		for(int i=0;i<6;i++){
			Ball temp = this.ballArray.get(new Point(i,col));
			if(temp==null)
				return i;
		}
		return 6;
	}
	public boolean isGameOver(){
		for(int i=0;i<6;i++){
			for(int j=0;j<6;j++){
				if(this.ballArray.get(new Point(i,j))==null){
					return false;
				}
			}
		}
		return true;
	}
	public boolean checkBallCol(char c, int col,int row){
		if(c!='0'){
			int temp = c -'0';
			int count = 0;
			for(int i=col; i>=0 ; i--){
				if(this.ballArray.get(new Point(row,i))!=null)
					count++;
				else
					break;
			}
			for(int i=col+1; i<6 ; i++){
				if(this.ballArray.get(new Point(row,i))!=null)
					count++;
				else
					break;
			}
			if(count==temp){
				return true;
			}
		}
		return false;
		
	}
	
	public boolean checkBallRow(char c, int col,int row){
		if(c!='0'){
			int temp = c -'0';
			int count = 0;
			for(int i=row-1; i>=0 ; i--){
				if(this.ballArray.get(new Point(i,col))!=null){
					count++;
				}
				else
					break;
			}
			for(int i=row; i<6 ; i++){
				if(this.ballArray.get(new Point(i,col))!=null)
					count++;
				else
					break;
			}
			if(count==temp){
				return true;
			}
		}
		return false;
		
	}
	
	public boolean checkBall(char c,int col,int row){
		if(this.checkBallCol(c, col, row)||this.checkBallRow(c, col, row)){
			return true;
		}
		return false;
	}
	public boolean checkAllBalls(){
		
		for(int i =0; i<6;i++){
			for(int j=0;j<6;j++){
				Ball tempBall = this.ballArray.get(new Point(i,j));
				if(tempBall!=null){
					if(this.checkBall(tempBall.getType(), tempBall.getCol(), tempBall.getRow())){
						return false;
					}
				
				}
			}
		}
		return true;
	}
	private void checkSpecial(int col, int row){
		Ball temp = this.ballArray.get(new Point(row,col));
		if(temp==null)
			return ;
		if(temp.isSpecial()){
			temp.changeToNormal();
		}
	}
	private void changeTheBallAround(int col, int row){
		this.checkSpecial(col-1, row);
		this.checkSpecial(col+1, row);
		this.checkSpecial(col, row -1);
		this.checkSpecial(col, row+1);
	}

	private void clearBall(char c,int col,int row){
	
			this.changeTheBallAround(col, row);
			this.ballArray.put(new Point(row,col),null);
			this.score++;
	
		
	}
	public void clearBalls(){
	
		while(!this.checkAllBalls()){
			char[][] temp = new char[6][6]; 
			for(int i=0;i<6;i++){
				for(int j=0;j<6;j++){
					temp[i][j]=' ';
				}
			}
			for(int i =0; i<6;i++){
				for(int j=0;j<6;j++){
					Ball tempBall = this.ballArray.get(new Point(j,i));
					if(tempBall!=null){
						if(this.checkBall(tempBall.getType(), i, j)){
							temp[i][j]=tempBall.getType();
						}
					}
				}
			}
		
			
			for(int i=0;i<6;i++){
				for(int j=0;j<6;j++){
					if(temp[i][j]!=' '){
						this.clearBall(temp[i][j],i, j);
					}
				}
			}
			for( int i=0;i<6;i++){
				for(int j=1;j<6;j++){
					Ball tempBall = this.ballArray.get(new Point(j,i));
					if(tempBall!=null){
						for(int k=j-1;k>=0;k--){
							if(this.ballArray.get(new Point(k,i))==null){
								int m = k+1;
								while(this.ballArray.get(new Point(m,i))!=null){
									this.ballArray.put(new Point(m-1,i), this.ballArray.get(new Point(m,i)));
									this.ballArray.put(new Point(m,i),null);
									m++;
								}
							}
						}
					}
				}
			
			}
			this.print();
		}
		
	
		
	}
	
	//choose the column to put the ball
	public void chooseCol(int col){
		
			if(!this.isGameOver()){
				Ball temp = new Ball(this.getLowestRow(col),col,this.ball.getType());
				this.ballArray.put(new Point(temp.getRow(),temp.getCol()),temp);
				this.ball=this.getNextRandomBall();
				this.print();
				this.clearBalls();
			}
		
	}

}
